//package com.competition.web.admin.service.impl;
//
//import java.sql.Time;
//import java.time.LocalDate;
//import java.time.LocalTime;
//import java.util.ArrayList;
//import java.util.Collection;
//import java.util.HashMap;
//import java.util.List;
//import java.util.Map;
//import java.util.concurrent.locks.ReentrantLock;
//import java.util.function.Function;
//import java.util.stream.Collectors;
//
//import javax.annotation.Resource;
//
//import org.slf4j.Logger;
//import org.slf4j.LoggerFactory;
//import org.springframework.core.ParameterizedTypeReference;
//import org.springframework.data.redis.core.HashOperations;
//import org.springframework.data.redis.core.ListOperations;
//import org.springframework.data.redis.core.RedisTemplate;
//import org.springframework.data.redis.core.ZSetOperations;
//import org.springframework.http.ResponseEntity;
//import org.springframework.stereotype.Service;
//
//import com.admin.param.contract.ISearchByVisitCustomerParam;
//import com.admin.param.contract.IUpdateGenereateResult;
//import com.admin.param.contract.IVisitCustomerRecordOfDay;
//import com.admin.vo.contract.IRegionVO;
//import com.admin.vo.contract.IStaffInfoVO;
//import com.admin.vo.contract.IStatisticsVisitVO;
//import com.admin.vo.contract.IVisitCustomerVO;
//import com.basic.service.impl.BaseServiceImpl;
//import com.common.util.BinarySearch;
//import com.common.util.CopyEntity;
//import com.common.util.ListConvertMap;
//import com.common.util.PositionUtil;
//import com.common.util.StringUtil;
//import com.common.util.TimeUtil;
//import com.competition.param.impl.ConditionItem;
//import com.competition.param.impl.VisitRequestParam;
//import com.competition.web.admin.config.HttpRequest;
//import com.competition.web.admin.mapper.VisitCustomerMapper;
//import com.competition.web.admin.service.IVisitCustomerService;
//import com.competition.web.admin.util.SpringBeanUtil;
//import com.competition.web.constant.RedisConstant;
//import com.competition.web.entity.GeoCodes;
//import com.competition.web.entity.GeoRegeo;
//import com.competition.web.entity.GeoRegeoPlanning;
//import com.competition.web.entity.GeoRoute;
//import com.competition.web.entity.GeoTransits;
//import com.competition.web.entity.VisitCustomer;
//import com.competition.web.entity.VisitCustomerExcel;
//import com.hungary.Hungary;
//import com.page.PageResponseData;
//import com.param.contract.IPage;
//import com.unify.type.Data;
//import com.unify.type.DataByStaff;
//import com.unify.type.ExploringHorsesResponse;
//import com.unify.type.IData;
//import com.unify.type.IExploringHorsesResponse;
//import com.unify.type.StaffInfo;
//import com.unify.type.StaffSeachByExploringHorses;
//import com.unify.type.TransferParam;
//import com.unify.type.TransferParam.Customer;
//import com.unify.type.Visit;
//
//@Service
//public class VisitCustomerServiceCopyImpl extends BaseServiceImpl<VisitCustomer> implements IVisitCustomerService {
//
//	private static final long serialVersionUID = 1L;
//
//	private static Logger LOGGER = LoggerFactory.getLogger(VisitCustomerServiceCopyImpl.class);
//
//	private RedisTemplate<String, Object> redisTemplate;
//
//	private HttpRequest httpRequest;
//
//	private static Map<String, Integer> STATUS = new HashMap<String, Integer>();
//
//	static Time noon = Time.valueOf("12:00:00");
//
//	static Map<String, String> AREA_DATA = new HashMap<String, String>();
//
//	static Map<Integer, Integer> CONDITION_MAP = new HashMap<Integer, Integer>();
//	
//	/**
//	 * 拜访时间字段
//	 */
//	static Map<Integer, String> VISIT_TIME_COLUMN = new HashMap<Integer, String>();
//	
//	
////	ReentrantLock reentrantLock = new ReentrantLock()
//	
//	
//	/**
//	 * 探马 指派字段
//	 */
//	static Map<Integer, String> ASSIGN_COLUMN = new HashMap<Integer, String>();
//	
//	static {
//
//		AREA_DATA.put("上海省", "上海");
//
//		AREA_DATA.put("北京省", "北京");
//
//		AREA_DATA.put("重庆省", "重庆");
//
//		AREA_DATA.put("天津省", "天津");
//
//		AREA_DATA.put("上海市", "上海");
//
//		AREA_DATA.put("北京市", "北京");
//
//		AREA_DATA.put("重庆市", "重庆");
//
//		AREA_DATA.put("天津市", "天津");
//
//		AREA_DATA.put("上海", "上海");
//
//		AREA_DATA.put("北京", "北京");
//
//		AREA_DATA.put("重庆", "重庆");
//
//		AREA_DATA.put("天津", "天津");
//
//		/**
//		 *  有 131723 这个key 代表 二访
//	 *  99808 --> 首访核单状态
//	 *  130418 ---> 回访核单状态
//	 *  
//	 *  0 前道 1 后道
//		 */
//		CONDITION_MAP.put(131723, 1);
//		
//		CONDITION_MAP.put(99808, 0);
//		
//		CONDITION_MAP.put(130228, 1);
//		
//		
//		ASSIGN_COLUMN.put(130228, "131591");
//		
//		ASSIGN_COLUMN.put(99808, "100490");
//		
//		ASSIGN_COLUMN.put(131723, "");
//		
//		
//		VISIT_TIME_COLUMN.put(99808, "98173");
//		
//		VISIT_TIME_COLUMN.put(130228, "130228");
//		
//		VISIT_TIME_COLUMN.put(131723, "131723");
//		
//	
//	}
//	
//
//	// 测试代码 ============================================
////	private ObjectMapper objectMapper = new ObjectMapper();
//
////	List<List<VisitCustomerVO>> visLists;
//
////	{
////		try {
////
////			FileInputStream fileInputStream = new FileInputStream(
////					new File(VisitCustomerServiceImpl.class.getClassLoader().getResource("./city.json").getPath()));
////
////			byte[] buffer = new byte[4096];
////
////			ByteArrayOutputStream arrayInputStream = new ByteArrayOutputStream();
////
////			while (-1 != fileInputStream.read(buffer)) {
////				arrayInputStream.write(buffer);
////			}
////
////			byte[] res = arrayInputStream.toByteArray();
////
////			visLists = objectMapper.readValue(res, new TypeReference<List<List<VisitCustomerVO>>>() {
////			});
////
////			fileInputStream.close();
////
////		} catch (IOException e) {
////			// TODO Auto-generated catch block
////			e.printStackTrace();
////		}
////	}
//
//	// 测试代码 end==================================================
//
//	static {
//		// 类型（前道/后道）
//		STATUS.put("前道", 0);
//
//		STATUS.put("后道", 1);
//	}
//
//	public VisitCustomerServiceCopyImpl(VisitCustomerMapper mapper) {
//		super(mapper);
//	}
//
//	protected void insertPropteris(VisitCustomer data) {
//		long time = System.currentTimeMillis() / 1000;
//		data.setCreateTime(time);
//		data.setUpdateTime(time);
//	}
//
//	protected void updatePropteris(VisitCustomer data) {
//		data.setUpdateTime(System.currentTimeMillis() / 1000);
//	}
//
//	protected Class<VisitCustomer> getEntityClass() {
//		return VisitCustomer.class;
//	}
//
//	@Override
//	public <VO, StaffInfoVO extends IStaffInfoVO> void batchInsertReciveIds(List<VisitCustomerExcel> visitCustomers,
//			Map<String, StaffInfoVO> map, Class<VO> target, int adminId, String token) {
//
//		// 提前清空数据 ==========================================
//
////		HashOperations<String, String, Integer> hashOperations = redisTemplate.opsForHash();
//
////		if (!hashOperations.hasKey(RedisConstant.STATISTICS_DAY, "day")) {
////			hashOperations.put(RedisConstant.STATISTICS_DAY, "day", 1);
////		}
//
//		this.cleanCacheByVisitCustomer(token);
//
//		redisTemplate.delete(RedisConstant.getAlgResultKey(token));
//
//		redisTemplate.delete(RedisConstant.getUpdateKey(token));
//
//		// =======================================================
//
//		List<VisitCustomer> customers = new ArrayList<VisitCustomer>();
//
//		VisitCustomer visit;
//
//		String userName;
//
//		VO vo;
//
//		int i = 0;
//
//		LocalDate localDate;
//
//		String type;
//
//		LocalTime time;
//
//		Integer typeRes;
//
//		for (VisitCustomerExcel visitCustomerExcel : visitCustomers) {
//
//			visit = CopyEntity.copyEntity(visitCustomerExcel, VisitCustomer.class);
//
//			userName = visitCustomerExcel.getUserName();
//
//			if (map.containsKey(userName)) {
//				visit.setUserId(map.get(userName).getId());
//
//				visit.setAssignPersonnel(1);
//			}
//
//			localDate = visitCustomerExcel.getDay();
//
//			if (null == localDate) {
//				throw new RuntimeException("日期不能为空");
//			}
//
//			visit.setDay(TimeUtil.getTimestamps(localDate) / 1000);
//
//			type = visitCustomerExcel.getType();
//
//			if (null == type) {
//				throw new RuntimeException("类型不能为空");
//			}
//
//			typeRes = STATUS.get(type);
//
//			if (null == typeRes) {
//				throw new RuntimeException("类型只能是前道或后道");
//			}
//
//			visit.setType(typeRes.byteValue());
//
//			visit.setAdminId(adminId);
//
//			time = visitCustomerExcel.getTime();
//
//			if (null == time) {
//				throw new RuntimeException("时间不能为空");
//			}
//
//			visit.setTime(/* TimeUtil.getTimestamps( */Time.valueOf(time)/* ) */);
//
////			insertPropteris(visit);
//
//			visit.setId(i);
//
//			customers.add(visit);
//			i++;
//		}
//
////		生成结果在添加到数据里面
////		this.mapper.batchInsert(customers.stream().toArray(VisitCustomer[]::new));
//
//		ListOperations<String, Object> operations = redisTemplate.opsForList();
//
//		String visitKey = RedisConstant.getVisitCustomerKey(token);
//
////		redisTemplate.delete(visitKey);
//
//		// ======================================================
//
//		List<VO> vos = new ArrayList<VO>();
//
//		Map<Integer, StaffInfoVO> idAndUserName = new HashMap<Integer, StaffInfoVO>();
//
//		IStaffInfoVO staffInfoVO;
//
//		for (String key : map.keySet()) {
//
//			staffInfoVO = map.get(key);
//
//			idAndUserName.put(staffInfoVO.getId(), (StaffInfoVO) staffInfoVO);
//		}
//
//		for (VisitCustomer visitCustomer : customers) {
//
//			vo = CopyEntity.copyEntity(visitCustomer, target);
//
//			final IVisitCustomerVO visitCustomerVO = (IVisitCustomerVO) vo;
//
//			IStaffInfoVO staffInfo = idAndUserName.get(visitCustomerVO.getUserId());
//
//			if (null != staffInfo) {
//				visitCustomerVO.setUserName(staffInfo.getStaffName());
//			}
//
//			this.httpRequest.get(visitCustomer.getCompanyAddress(), visitCustomer.getCity(), GeoRegeo.class,
//					(ResponseEntity<GeoRegeo> t) -> {
//
//						byte b = (byte) 1;
//
//						GeoRegeo geoRegeo = t.getBody();
//
//						if (0 == geoRegeo.getCount()) {
//
//							visitCustomerVO.setAddressStatus(b);
//
//							visitCustomerVO.setLongitude(0d);
//
//							visitCustomerVO.setLatitude(0d);
//
//							vos.add((VO) visitCustomerVO);
//
//							return;
//
//						} else {
//							visitCustomerVO.setAddressStatus((byte) 0);
//						}
//
//						List<GeoCodes> geoCodes = geoRegeo.getGeocodes();
//
//						GeoCodes codes = geoCodes.get(0);
//
//						String[] location = codes.getLocation().split(",");
//
//						visitCustomerVO.setLongitude(Double.valueOf(location[0]));
//
//						visitCustomerVO.setLatitude(Double.valueOf(location[1]));
//
//						if (null != staffInfo) {
//
//							visitCustomerVO.setMeLatitude(staffInfo.getLatitude());
//
//							visitCustomerVO.setMeLongitude(staffInfo.getLongitude());
//						}
//
//						vos.add((VO) visitCustomerVO);
//
//						operations.leftPush(visitKey, visitCustomerVO);
//					});
//		}
//	}
//
//	@Override
//	public <VO extends IVisitCustomerVO> void exploringHorsesToRedis(List<VO> visitCustomers, String token) {
//
//		ListOperations<String, Object> listOperations = redisTemplate.opsForList();
//
//		String visitKey = RedisConstant.getVisitCustomerKey(token);
//
//		this.cleanCacheByVisitCustomer(token);
//
//
//		redisTemplate.delete(RedisConstant.getAlgResultKey(token));
//
//		redisTemplate.delete(RedisConstant.getUpdateKey(token));
//
////		latitude and longitude
//
//		Double latitude /* 纬度 */;
//
//		for (VO visitCustomerVO : visitCustomers) {
//
//			//
//			latitude = visitCustomerVO.getLatitude();
//
//			if (null != latitude) {
//				listOperations.rightPush(visitKey, visitCustomerVO);
//				continue;
//			}
//
//			// 请求地图
//
//			this.httpRequest.get(visitCustomerVO.getCompanyAddress(), visitCustomerVO.getCity(), GeoRegeo.class,
//					(ResponseEntity<GeoRegeo> t) -> {
//
//						byte b = (byte) 1;
//
//						GeoRegeo geoRegeo = t.getBody();
//
//						if (0 == geoRegeo.getCount()) {
//							
//							LOGGER.debug("规划有误， 城市：{}， 公司：{}", visitCustomerVO.getCity(), visitCustomerVO.getCompanyName());
//
//							visitCustomerVO.setAddressStatus(b);
//
//							visitCustomerVO.setLongitude(0d);
//
//							visitCustomerVO.setLatitude(0d);
//
//							return;
//
//						} else {
//							visitCustomerVO.setAddressStatus((byte) 0);
//						}
//
//						List<GeoCodes> geoCodes = geoRegeo.getGeocodes();
//
//						GeoCodes codes = geoCodes.get(0);
//
//						String[] location = codes.getLocation().split(",");
//
//						visitCustomerVO.setLongitude(Double.valueOf(location[0]));
//
//						visitCustomerVO.setLatitude(Double.valueOf(location[1]));
//
//						listOperations.rightPush(visitKey, visitCustomerVO);
//					});
//
//		}
//
////		List<VO> vos = visitCustomers.subList(0, 100);
////		
////		PageResponseData<VO> pageResponseData = new PageResponseData<VO>(visitCustomers.size(), visitCustomers);
//
//	}
//
//	/**
//	 * 
//	 */
//	public <VO> PageResponseData<VO> getVOs(int pageNum, String token, Map<Integer, IRegionVO> map,
//			Map<String, IRegionVO> cityRegionMap) {
//
//		ListOperations<String, Object> operations = redisTemplate.opsForList();
//
//		String key = RedisConstant.getVisitCustomerKey(token);
//
//		int readNumber = (pageNum - 1) * 100;
//
//		List<VO> vos = (List<VO>) operations.range(key, readNumber, 100);
//
//		IVisitCustomerVO customerVO;
//
//		String cityName;
//
//		Integer areaId;
//
//		IRegionVO regionVO, cityRegion;
//
//		int i = 0;
//
//		for (VO vo : vos) {
//
//			customerVO = (IVisitCustomerVO) vo;
//
//			cityName = customerVO.getCity();
//
//			cityRegion = cityRegionMap.get(cityName);
//
//			if (null == cityRegion) {
//				i++;
//				continue;
//			}
//
//			customerVO.setCityId(cityRegion.getId());
//
//			areaId = cityRegion.getParentid();
//
//			regionVO = map.get(areaId);
//
//			if (null != regionVO) {
//				customerVO.setAreaId(areaId);
//
//				customerVO.setAreaName(regionVO.getName());
//			}
//
//			operations.set(key, i, customerVO);
//
//			i++;
//		}
//
//		return new PageResponseData<VO>(operations.size(key), vos);
//	}
//
//	private <VO extends IVisitCustomerVO> List<VO> getVisitCustomer(int pageNum, String token) {
//
//		RedisTemplate<String, VO> redisTemplate = SpringBeanUtil.getBean("redisTemplate");
//
//		ListOperations<String, VO> operations = redisTemplate.opsForList();
//
////		long size = operations.size(RedisConstant.getVisitCustomerKey(token));
//
//		int readNumber = (pageNum - 1) * 100;
//
//		String key = RedisConstant.getVisitCustomerKey(token);
//
//		return operations.range(key, readNumber, 100);
//
////		List<VO> list = new ArrayList<VO>();
//
////		VO vo;
////		
////		for (int i = 0; i < 100; i++) {
////			
////			vo = (VO) operations.leftPop(key);
////			
////			if (null == vo) {
////				break;
////			}
////			
////			list.add((VO) operations.leftPop(key));
////			
////		}
////		
////		return list;
////		operations.s
//
//	}
//
//	/**
//	 * 获取未指定的客户
//	 * 
//	 * @param pageNum
//	 * @param token
//	 * @return
//	 */
//	public List<IVisitCustomerVO> getCustomerVOsFromCache(int pageNum, String token) {
//
//		/**
//		 * 要拜访的客户
//		 */
//		return this.getVisitCustomer(pageNum, token);
//
////		// 过滤指定的
////		return customerVOs.stream().filter(e -> 0 == e.getAssignPersonnel()).collect(Collectors.toList());
//	}
//
//	// 利用匈牙利算法求解[[31077.3006, 26427.8561], [23674.2962, 18819.3745]]
//	// [[26427.859369257796, 31077.304462913366], [23674.299127004662,
//	// 18819.376868572974]]
//
//	// [[31.146099999999933, 0.0], [0.0, 0.0]]
//
//	// [[0, 1], [1, 0]]
//
//	/**
//	 * 8(靳强住址：-上海市七宝镇) 9(李四住址：-上海市浦东新区世纪大道) (客户地址33)上海市新场地铁站 1(31077.3006米)
//	 * 0(26427.8561米) (客户地址32)上海市鹤沙航城地铁站 0(23674.2962米) 1(18819.3745米)
//	 * 
//	 */
//
////	Hungary hungary = new Hungary(data);
//
////	hungary.algrm();
//
//	// 获取结果
////	int[][] result = hungary.getMatch();
//
////	int[][] second = HungarianAlgorithm.hgAlgorithmAssignments(data, "max");
//
////	hashOperations.put(RedisConstant.VISIT_TO_COMPANY_DISTANCE, RedisConstant.VISIT_TO_COMPANY_DISTANCE, result);
//
////	hashOperations.put(RedisConstant.VISIT_SELECT, RedisConstant.VISIT_SELECT, vos);
//	/**
//	 * @param vos 选择的员工
//	 * @param pageNum 页码
//	 */
//	@Override
//	public <VO extends IStaffInfoVO> void genreateResult(List<VO> vos, int pageNum, String token,
//			List<IVisitCustomerVO> customerVOs) {
//
//		if (0 == vos.size()) {
//			return;
//		}
//
//		// 计算各个员工到客户的距离
////		int len = customerVOs.size();
//
////		double[][] data = new double[len][];
//
//		HashOperations<String, String, Object> hashOperations = redisTemplate.opsForHash();
//
//		String pageKey = RedisConstant.getPageNumKey(token);
//
//		hashOperations.put(pageKey, pageKey, pageNum);
//
////		double[] row;
////
////		int i = 0, j = 0;
//
//		String noonKey = RedisConstant.getVisitKeyNoon(token);
//
//		String afternoonKey = RedisConstant.getVisitKeyAfterNoon(token);
//
//		for (IStaffInfoVO staff : vos) {
//
////			visits = new ArrayList<>();
//
////			row = new double[len];
//
//			for (IVisitCustomerVO iVisitCustomerVO : customerVOs) {
//
//				computerDistanceAndDuration(iVisitCustomerVO, staff, hashOperations, noonKey, afternoonKey);
//
////				row[j] = distance;
////				j++;
//			}
//
////			data[i] = row;
////			j = 0;
////			i++;
//		}
//
//	}
//
//	public <VO extends IStaffInfoVO> void computerAssginsInfo(int pageNum, String token, List<VO> vos) {
//
//		List<IVisitCustomerVO> customerVOs = this.getCustomerVOsFromCache(pageNum, token);
//
//		Map<Integer, VO> map = ListConvertMap.listToMap(vos, VO::getId);
//
//		HashOperations<String, String, IVisitCustomerVO> hashOperations = redisTemplate.opsForHash();
//
//		String key = RedisConstant.getAssignKey(token);
//
//		VO vo;
//
//		Integer assignId;
//
//		double distance;
//
//		byte error = 1;
//
//		for (IVisitCustomerVO iVisitCustomerVO : customerVOs) {
//
//			assignId = iVisitCustomerVO.getUserId();
//
//			if (null == assignId) {
//				continue;
//			}
//
//			vo = map.get(assignId);
//
//			if (null == vo) {
//				continue;
//			}
//
//			distance = PositionUtil.getDistanceByGD(vo.getLongitude(), vo.getLatitude(),
//					iVisitCustomerVO.getLongitude(), iVisitCustomerVO.getLatitude());
//
//			iVisitCustomerVO.setDistance(distance);
//
//			iVisitCustomerVO.setMeLongitude(vo.getLongitude());
//
//			iVisitCustomerVO.setMeLatitude(vo.getLatitude());
//
//			iVisitCustomerVO.setUserName(vo.getStaffName());
//
//			String origin = vo.getLongitude() + "," + vo.getLatitude();
//
//			String dest = iVisitCustomerVO.getLongitude() + "," + iVisitCustomerVO.getLatitude();
//
//			httpRequest.getBusRoutePlanning(origin, dest, vo.getAreaName(), iVisitCustomerVO.getCity(),
//					GeoRegeoPlanning.class, (t) -> {
//
//						GeoRegeoPlanning geoRoute = t.getBody();
//
//						if (0 == geoRoute.getCount()) {
//
//							iVisitCustomerVO.setAddressStatus(error);
//
//							iVisitCustomerVO.setDuration(0);
//
//							hashOperations.put(key, iVisitCustomerVO.getId() + "", iVisitCustomerVO);
//
//							return;
//
//						}
//
//						GeoRoute route = geoRoute.getRoute();
//
//						List<GeoTransits> geoTransits = route.getTransits();
//						// 默认取第一个
//
//						GeoTransits geoTransit = geoTransits.get(0);
//
//						iVisitCustomerVO.setDuration(geoTransit.getDuration());
//
//						hashOperations.put(key, iVisitCustomerVO.getId() + "", iVisitCustomerVO);
//					});
//		}
//	}
//
//	private <VO extends IStaffInfoVO> void computerDistanceAndDuration(IVisitCustomerVO iVisitCustomerVO, VO staff,
//			HashOperations<String, String, Object> hashOperations, String noonKey, String afternoonKey) {
//
//		byte statusHave = 1, statusNo = 0;
//
//		final double distance = PositionUtil.getDistanceByGD(staff.getLongitude(), staff.getLatitude(),
//				iVisitCustomerVO.getLongitude(), iVisitCustomerVO.getLatitude());
//
//		String origin = staff.getLongitude() + "," + staff.getLatitude();
//
//		String dest = iVisitCustomerVO.getLongitude() + "," + iVisitCustomerVO.getLatitude();
//
//		// 小于 2km 的采用 步行规划
//		// TODO
//		if (distance < 2000) {
//
//		}
//
//		// 计算耗时
//		httpRequest.getBusRoutePlanning(origin, dest, staff.getAreaName(), iVisitCustomerVO.getCity(),
//				GeoRegeoPlanning.class, (t) -> {
//					GeoRegeoPlanning geoRoute = t.getBody();
//
////				System.out.println("origin: " + origin + ", dest: " + dest + ", distance: " + distance);
//
//					Visit visit = new Visit();
//
//					int clientId = iVisitCustomerVO.getId();
////					
//					visit.setClientId(clientId);
//
//					int id = staff.getId();
//
//					visit.setStaffId(id);
//
//					visit.setStaffName(staff.getStaffName());
//
//					visit.setDistance(distance);
//
//					boolean isNoon = iVisitCustomerVO.getTime().before(noon);
//
//					Integer count = geoRoute.getCount();
//					if (0 == count) {
//
//						visit.setStatus(statusNo);
//
//						LOGGER.debug("路径规划有{}条", count);
//						
//						if (isNoon) {
//							hashOperations.put(noonKey, "hash-" + clientId + "-" + id, visit);
//
//							
//							return;
//						}
//
//						hashOperations.put(afternoonKey, "hash-" + clientId + "-" + id, visit);
//
//						return;
//					}
//
//					GeoRoute route = geoRoute.getRoute();
//
//					List<GeoTransits> geoTransits = route.getTransits();
//					// 默认取第一个
//
//					GeoTransits geoTransit = geoTransits.get(0);
//
//					visit.setStatus(statusHave);
//
//					visit.setDuration(geoTransit.getDuration());
//
////					visits.add(visit);
//
//					if (isNoon) {
//						// 是 上午
//						hashOperations.put(noonKey, "hash" + clientId + "," + id, visit);
//						return;
//					}
////					只计算下午的
////					// 下午
////					hashOperations.put(afternoonKey, "hash-afternoon" + clientId + "," + id, visit);
//				});
//
//	}
//
//	@Override
//	public <VO extends IStaffInfoVO> void genreateResultByLists(
//			List<List<VO>> vos, int pageNum, String token,
//			List<List<IVisitCustomerVO>> customerVOs) {
//
//		int size = vos.size();
//
//		int vSize = customerVOs.size();
//
//		if (size != vSize) {
//			throw new Error("数据不匹配");
//		}
//
//		// 只计算上午的
//		int i = 0;
//		
////		for (int i = 0; i < size; i++) {
//		genreateResult(vos.get(i), pageNum, token, customerVOs.get(i));
////		}
//	}
//
//	@Override
//	public void customerTransfer(String token) {
//
//		String algKey = RedisConstant.getAlgResultKey(token);
//
//		ListOperations<String, Object> listOperations = redisTemplate.opsForList();
//
//		List<List<IVisitCustomerVO>> lists = this.getListsFromIVisitCustomerVO(listOperations, algKey);
//
//		List<VisitCustomer> customersList = statisticsResult(lists);
//
//		StaffSeachByExploringHorses seachByExploringHorses;
//
//		ParameterizedTypeReference<ExploringHorsesResponse<DataByStaff<StaffInfo>>> parameterizedTypeReference = new ParameterizedTypeReference<ExploringHorsesResponse<DataByStaff<StaffInfo>>>() {
//		};
//
//		for (List<IVisitCustomerVO> visitCustomers : lists) {
//
//			for (IVisitCustomerVO visitCustomer : visitCustomers) {
//
//				seachByExploringHorses = new StaffSeachByExploringHorses();
//
//				String userName = visitCustomer.getUserName();
//				seachByExploringHorses.setName(userName);
//
//				this.httpRequest.getStaffByExploringHorsesSync(seachByExploringHorses, parameterizedTypeReference,
//						(t) -> {
//
//							if (0 != t.getCode()) {
//
//								LOGGER.error("搜索员工失败， {}", t.getMessage());
//
//								return;
//							}
//
//							DataByStaff<StaffInfo> data = t.getData();
//
//							if (0 == data.getTotalCount()) {
//								// 找不到员工
//								LOGGER.error("找不到员工， {}", userName);
//								return;
//							}
//
//							// 默认取第零个
//							StaffInfo staffInfo = data.getResult().get(0);
//
//							TransferParam param = new TransferParam();
//
//							param.setHandoverToUserid(staffInfo.getSalesId());
//
//							List<Customer> customers = new ArrayList<TransferParam.Customer>();
//
//							Customer customer = new Customer();
//
//							customer.setCustomerId(visitCustomer.getCustomerId());
//
//							customer.setQwUserId(visitCustomer.getQwSalesld());
//
//							customers.add(customer);
//							
//							param.setCustomers(customers);
//
//							ParameterizedTypeReference<ExploringHorsesResponse<Data>> reference = new ParameterizedTypeReference<ExploringHorsesResponse<Data>>() {
//							};
//
//							this.httpRequest.transfer(param, reference, (o) -> {
//
//								LOGGER.debug("转移结果: {}", o.getMessage());
//
//							});
//
//						});
//
//			}
//
//		}
//		
//		this.assignVisit(customersList, token);
//		
//		this.batchInsert(customersList.stream().toArray(VisitCustomer[]::new));
//		
//		this.cleanCacheByVisitCustomer(token);
//	}
//
//	/**
//	 * 统计各个员工派单数量 及更新派单日期
//	 * 
//	 * @param lists
//	 * @return 派单算法结果
//	 */
//	private List<VisitCustomer> statisticsResult(List<List<IVisitCustomerVO>> lists) {
//
//		VisitCustomer visitCustomer;
//
//		List<VisitCustomer> customers = new ArrayList<VisitCustomer>();
//
//		// 统计每个员工派单数目
//
//		String statisticsKey = RedisConstant.STATISTICS_VISIT;
//
//		char[] distinguishBetweenMorningAndAfternoon = new char[] { 'n', // 上午
//				'a' // 下午
//		};
//
//		HashOperations<String, String, Number> hashOperations = redisTemplate.opsForHash();
//
//		int i = 0;
//
//		char ch;
//
//		int staffId;
//
//		long stamp = System.currentTimeMillis();
//
//		long cacheTime = 0;
//
//		long res = stamp / 1000;
//
//		if (!hashOperations.hasKey(RedisConstant.STATISTICS_CURRENT_TIME, "time")) {
//
//			hashOperations.put(RedisConstant.STATISTICS_CURRENT_TIME, "time", res);
//
//			cacheTime = res;
//
//		} else {
//			cacheTime = hashOperations.get(RedisConstant.STATISTICS_CURRENT_TIME, "time").longValue();
//		}
//
//		long[] startAndEnd = TimeUtil.getDayStartOfEndByTimStamp(cacheTime);
//
//		out: if (res > startAndEnd[1]) {
//
//			// 更新当天日期
//			hashOperations.put(RedisConstant.STATISTICS_CURRENT_TIME, "time", res);
//
//			if (hashOperations.hasKey(RedisConstant.STATISTICS_DAY, "day")) {
//				hashOperations.increment(RedisConstant.STATISTICS_DAY, "day", 1);
//				break out;
//			}
//
//			hashOperations.put(RedisConstant.STATISTICS_DAY, "day", 1L);
//		}
//
//		String key;
//
//		for (List<IVisitCustomerVO> list : lists) {
//
//			ch = distinguishBetweenMorningAndAfternoon[i];
//
//			for (IVisitCustomerVO vo : list) {
//
//				visitCustomer = CopyEntity.copyEntity(vo, VisitCustomer.class);
//
//				visitCustomer.setId(null);
//
//				insertPropteris(visitCustomer);
//
//				customers.add(visitCustomer);
//
//				staffId = visitCustomer.getUserId();
//
//				key = ch + "-" + staffId;
//
//				if (hashOperations.hasKey(statisticsKey, key)) {
//					hashOperations.increment(statisticsKey, key, 1);
//					continue;
//				}
//				hashOperations.put(statisticsKey, key, 1L);
//			}
//			i++;
//		}
//
//		return customers;
//
//	}
//	
//	/**
//	 *  VO --> Entity
//	 * @param lists
//	 * @return
//	 */
//	private List<VisitCustomer> customerVOsToEntity(List<List<IVisitCustomerVO>> lists) {
//		
//		List<VisitCustomer> customers = new ArrayList<VisitCustomer>();
//		
//		VisitCustomer visitCustomer;
//		
//		for (List<IVisitCustomerVO> list : lists) {
//
//
//			for (IVisitCustomerVO vo : list) {
//
//				visitCustomer = CopyEntity.copyEntity(vo, VisitCustomer.class);
//
//				visitCustomer.setId(null);
//
//				insertPropteris(visitCustomer);
//
//				customers.add(visitCustomer);
//			}
//		}
//		
//		return customers;
//		
//	}
//
//	
//	private void assignVisit(List<VisitCustomer> customers, String token) {
//		
//
//		String assignKey = RedisConstant.getAssignKey(token);
//
//		HashOperations<String, String, IVisitCustomerVO> operations = redisTemplate.opsForHash();
//
//		// 指派结果
//		List<IVisitCustomerVO> customerVOs = operations.values(assignKey);
//
//		VisitCustomer visitCustomer;
//
////		if (null != customerVOs) {
//
//		for (IVisitCustomerVO visitCustomerVO : customerVOs) {
//
//			visitCustomer = CopyEntity.copyEntity(visitCustomerVO, VisitCustomer.class);
//
//			insertPropteris(visitCustomer);
//
//			visitCustomer.setId(null);
//			customers.add(visitCustomer);
//		}
//
//		
//	}
//	
//	/**
//	 * 统计各个员工派单数量 及更新派单日期 及指派结果
//	 * 
//	 * @param token
//	 * @param algKey 算法结果key
//	 * @return
//	 */
//	private List<VisitCustomer> parseStaticsAndAssignReturnVisitCustomers(String token, String algKey) {
//
//		ListOperations<String, Object> listOperations = redisTemplate.opsForList();
//
//		List<List<IVisitCustomerVO>> lists = this.getListsFromIVisitCustomerVO(listOperations, algKey);
//
//		if (null == lists) {
//			throw new Error("找不到算法结果");
//		}
//
//		List<VisitCustomer> customers = statisticsResult(lists);
//
//		assignVisit(customers, token);
//
//		return customers;
//
//	}
//
//	@Override
//	public int passVerification(String token) {
//
////		}
//
////		HashOperations<String, String, VisitCustomer> hashOperations = redisTemplate.opsForHash();
////		
////		
////		String dbKey = RedisConstant.getAlgResultToDBKey(token);
////		
////		List<VisitCustomer> customers = hashOperations.values(dbKey);
//
//		String algKey = RedisConstant.getAlgResultKey(token);
//
//		List<VisitCustomer> customers = parseStaticsAndAssignReturnVisitCustomers(token, algKey);
//
//		int insertNumber = this.batchInsert(customers.stream().toArray(VisitCustomer[]::new));
//
//		if (0 != insertNumber) {
//			redisTemplate.delete(algKey);
//
//			redisTemplate.delete(RedisConstant.getAssignKey(token));
//		}
//
//		return insertNumber;
//	}
//
//	protected List<List<IVisitCustomerVO>> getListsFromIVisitCustomerVO(ListOperations<String, Object> listOperations,
//			String algKey) {
//		Long size = listOperations.size(algKey);
//
//		if ( 0 == size) {
//			return null;
//		}
//
//		List<List<IVisitCustomerVO>> res = new ArrayList<List<IVisitCustomerVO>>();
//
//		int i = 0;
//		
//		for (; i < size; i++) {
//
//			res.add((List<IVisitCustomerVO>) listOperations.index(algKey, i));
//
//		}
//		return res;
//	}
//
//	// 处理时间 看看上下午时间安排是否冲突
//
//	// ================================================================
//	// 测试代码可以删掉
//	////
//
////	token = "eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJhZG1pbiIsImNyZWF0ZWQiOjE2OTQzOTgwNzk1NDYsImlkIjozLCJpYXQiOjE2OTQzOTgwNzksImV4cCI6MTY5NTAwMjg3OX0.AJ0VltsL89g-I2Ty1TqJ2OIlnClCOwt28_LwsAUfkPI";
////	
////	List<List<IVisitCustomerVO>> lists = new ArrayList<List<IVisitCustomerVO>>();
////	
////	List<? extends IVisitCustomerVO> noon = visLists.get(0);
////	
////	List<? extends IVisitCustomerVO> afternoon = visLists.get(1);
////	
////	List<IVisitCustomerVO> a = new ArrayList<IVisitCustomerVO>();
////	
////	List<IVisitCustomerVO> b = new ArrayList<IVisitCustomerVO>();
////
////	
////	for (IVisitCustomerVO iVisitCustomerVO2 : noon) {
////		a.add(iVisitCustomerVO2);
////	}
////	
////	for (IVisitCustomerVO iVisitCustomerVO2 : afternoon) {
////		b.add(iVisitCustomerVO2);
////	}
////	
////	lists.add(a);
////	
////	lists.add(b);
//
//	// ================================================================
//	// 覆盖算法处理
//
////	
////	// 时间冲突 优先修改下午的派单
////	
////	List<IVisitCustomerVO> confilctArraysAfternoons = visitLists.get(1);
////	
////	List<IVisitCustomerVO> confilctArraysNoon = visitLists.get(0);
////	
////	List<IVisitCustomerVO> afternooeList = lists.get(1);
////	
////	List<IVisitCustomerVO> nooeList = lists.get(0);
////	
////	String afternoonKey = RedisConstant.getVisitKeyAfterNoon(token);
////
////	String noonKey = RedisConstant.getVisitKeyNoon(token);
//////	
////	List<Object> afternoonValues = hashOperations.values(afternoonKey);
////
////	List<Object> noonValues = hashOperations.values(noonKey);
////
////	Map<Integer, List<Object>> mapNoonValues = ListConvertMap.listToMapList(noonValues,
////			e -> ((Visit) e).getStaffId());
////
////	Map<Integer, List<Object>> mapAfternoonValues = ListConvertMap.listToMapList(afternoonValues,
////			e -> ((Visit) e).getStaffId());
////
//////	
////	String visitKey = RedisConstant.getVisitCustomerKey(token);
////
////	List<Object> objectList = listOperations.range(visitKey, 0, listOperations.size(visitKey));
////
////	Map<Integer, Object> objectVisitCustomer = ListConvertMap.listToMap(objectList,
////			e -> ((IVisitCustomerVO) e).getId());
////
////	IVisitCustomerVO visitCustomerVONoon, visitCustomerVOAfternoon;
////
////	long conflict, afterConflict;
////
////	Integer clientId;
////
////	List<Object> visitsAfternoon;
////
////	// 清理掉下午的
////	lists.remove(1);
////
////	Visit visit;
////
////	List<IVisitCustomerVO> afternoonList = new ArrayList<IVisitCustomerVO>();
////
////	for (Integer integer : mapNoonValues.keySet()) {
////
////		visitsAfternoon = (List<Object>) mapAfternoonValues.get(integer);
////
////		if (null == visitsAfternoon) {
////
////			// 此员工没有安排在下午
////
////			// 随机挑一个
////
////			// TODO
////
////			continue;
////		}
////
////		List<Object> noonVisist = mapNoonValues.get(integer);
////
////		for (Object object : noonVisist) {
////
////			Visit itemVisit = (Visit) object;
////
////			// 上午的公司
////			visitCustomerVONoon = (IVisitCustomerVO) objectVisitCustomer.get(itemVisit.getClientId());
////
////			// 上午 + 2h + 去上午客户公司的时间
////			conflict = visitCustomerVONoon.getTime().getTime() + 7200000 + itemVisit.getDuration();
////
////			for (Object obj : visitsAfternoon) {
////
////				visit = (Visit) obj;
////
////				clientId = visit.getClientId();
////				// 获取下午公司通勤时间
////
////				visitCustomerVOAfternoon = (IVisitCustomerVO) objectVisitCustomer
////						.get(itemVisit.getClientId());
////
////				afterConflict = visitCustomerVOAfternoon.getTime().getTime();
////
////				if (conflict > afterConflict) {
////					continue;
////				}
////
////				visitCustomerVOAfternoon.setUserId(integer);
////
////				visitCustomerVOAfternoon.setDuration(visit.getDuration());
////
////				visitCustomerVOAfternoon.setDistance(visit.getDistance());
////
////				afternoonList.add(visitCustomerVOAfternoon);
////			}
////		}
////	}
////
////	lists.add(afternoonList);
////
////}
////
//
//	@Override
//	public Map<String, Object> getAlgResult(String token) {
//
//		HashOperations<String, String, Object> hashOperations = redisTemplate.opsForHash();
//
//		List<Object> visits = hashOperations.values(RedisConstant.getVisitKeyNoon(token));
//		
//		List<Object> visitsAfterNoon = hashOperations.values(RedisConstant.getVisitKeyAfterNoon(token));
//		
//		Map<String, Object> alg = new HashMap<String, Object>();
//		
//		alg.put("visitNoon", visits);
//		
//		alg.put("visitsAfternoon", visitsAfterNoon);
//		
//		return alg;
//	}
//
//	@Override
//	public <VO extends IStaffInfoVO> List<List<IVisitCustomerVO>> getGenreateManyResult(
//			String token/* ,List<VO> staffList */) {
//
//		ListOperations<String, Object> listOperations = redisTemplate.opsForList();
//
//		String algKey = RedisConstant.getAlgResultKey(token);
//
//		List<List<IVisitCustomerVO>> lists = getListsFromIVisitCustomerVO(listOperations, algKey);
//
//		if (null != lists && 0 != lists.size()) {
//			return lists;
//		}
//
//		List<Function<String, String>> functions = new ArrayList<Function<String, String>>();
//
//		functions.add(RedisConstant::getVisitKeyNoon);
//
//		functions.add(RedisConstant::getVisitKeyAfterNoon);
//////
//		HashOperations<String, String, Object> hashOperations = redisTemplate.opsForHash();
//////
//		String key = RedisConstant.getPageNumKey(token);
//
//		Number pageNum = (Number)hashOperations.get(key, key);
//		
//		List<IVisitCustomerVO> customerVOs;
//		
//		if (null == pageNum ) { // 全都是指派的
//			customerVOs = new ArrayList<IVisitCustomerVO>();
//		} else {
//			customerVOs = this.getVisitCustomer(pageNum.intValue(), token);
//		}
//
//		List<List<IVisitCustomerVO>> visitList = distinguishBetweenMorningAndAfternoon(
//				customerVOs.stream().filter(e -> 0 == e.getAssignPersonnel()).collect(Collectors.toList()));
//
//		int i = 0;
//
//		lists = new ArrayList<List<IVisitCustomerVO>>();
//
//		List<IVisitCustomerVO> addCache;
//
//		String[] keys = new String[2];
//
//		keys[0] = RedisConstant.getAlgNoonKey(token);
//
//		keys[1] = RedisConstant.getAlgAfternoonKey(token);
//
//		for (Function<String, String> function : functions) {
//
//			addCache = getGenreateResult(token, function, visitList.get(i), keys[i]);
//
//			lists.add(addCache);
//
//			i++;
//		}
////
//////		List<IVisitCustomerVO> assigins = customerVOs.stream().filter(e -> 0 != e.getAssignPersonnel())
//////				.collect(Collectors.toList());
////
//
//		// // 处理 已指定的
//		String assignKey = RedisConstant.getAssignKey(token);
//
//		List<Object> objects = hashOperations.values(assignKey);
//
//		i = 0;
//
//		for (Object object : objects) {
//
//			IVisitCustomerVO iVisitCustomerVO = (IVisitCustomerVO) object;
//
//			if (iVisitCustomerVO.getTime().before(noon)) {
//				// 上午
//
//				addCache = lists.get(0);
//				addCache.add(iVisitCustomerVO);
//
//			} else {
//				addCache = lists.get(1);
//				addCache.add(iVisitCustomerVO);
//			}
//
//			i++;
//		}
//
//		// 时间 处理标志
//		int flag = 0;
//
//		for (List<IVisitCustomerVO> visitCustomerVOs : lists) {
//
//			if (0 == visitCustomerVOs.size()) {
//				// 说明都在上午 或下午
//				flag = 1;
//			}
//
//		}
//
//		// 如果上午或下午为空 那就不用处理了
//		// 检查 已指派是否冲突
//		if (1 != flag) {
//
//			List<List<IVisitCustomerVO>> visitLists = new ArrayList<List<IVisitCustomerVO>>();
//
//			/* boolean res = */ parseTimeConflict(lists, visitLists);
//
////					if (res) {
////
////						
////					}
//
//		}
//		
//		//
//		
//		for (List<IVisitCustomerVO> visitCustomerVOs : lists) {
//
//			listOperations.rightPush(algKey, visitCustomerVOs);
//			
//		}
//
//		// 清理缓存
////		this.cleanCacheByVisitCustomer(token);
//
//		return lists;
//	}
//
//	/**
//	 * 时间是否冲突
//	 * 
//	 * @param lists
//	 * @return true 冲突 false 正常
//	 */
//	protected boolean parseTimeConflict(List<List<IVisitCustomerVO>> lists, List<List<IVisitCustomerVO>> visitLists) {
//
//		// 获取上午与下午的交集
//
//		Map<Integer, IVisitCustomerVO> noonMap = new HashMap<Integer, IVisitCustomerVO>();
//
//		Map<Integer, IVisitCustomerVO> afternoonMap = new HashMap<Integer, IVisitCustomerVO>();
//
//		List<IVisitCustomerVO> visitCustomerVOsNoon = lists.get(0);
//
//		List<IVisitCustomerVO> visitCustomerVOsAfternoon = lists.get(1);
//
//		for (IVisitCustomerVO iVisitCustomerVO : visitCustomerVOsNoon) {
//			noonMap.put(iVisitCustomerVO.getUserId(), iVisitCustomerVO);
//		}
//
//		for (IVisitCustomerVO iVisitCustomerVO : visitCustomerVOsAfternoon) {
//			afternoonMap.put(iVisitCustomerVO.getUserId(), iVisitCustomerVO);
//		}
//
//		List<IVisitCustomerVO> customerVOs = new ArrayList<IVisitCustomerVO>();
//
//		// 对比上下午有没有相同的员工
//
//		IVisitCustomerVO mapCustomerVO;
//
//		for (Integer integer : afternoonMap.keySet()) {
//
//			mapCustomerVO = noonMap.get(integer);
//
//			if (null != mapCustomerVO) {
//
//				customerVOs.add(mapCustomerVO);
//
//				customerVOs.add(afternoonMap.get(integer));
//			}
//		}
//
//		if (0 == customerVOs.size()) {
//			// 上下午行程 没有同一个员工
//			return false;
//		}
//
//		// 上下午行程 有同一个员工
//
//		// 判断时间冲突
//
//		// 分组
//
//		Map<Integer, List<IVisitCustomerVO>> map = new HashMap<Integer, List<IVisitCustomerVO>>();
//
//		List<IVisitCustomerVO> mapItem;
//
//		Integer uId;
//
//		for (IVisitCustomerVO iVisitCustomerVO : customerVOs) {
//
//			uId = iVisitCustomerVO.getUserId();
//
//			mapItem = map.get(uId);
//
//			if (null == mapItem) {
//
//				mapItem = new ArrayList<IVisitCustomerVO>();
//
//				mapItem.add(iVisitCustomerVO);
//
//				map.put(uId, mapItem);
//
//			} else {
//				mapItem.add(iVisitCustomerVO);
//			}
//		}
//
//		Time time, timenoon = null, afternoonTime = null;
//
//		byte one = 1;
//
//		IVisitCustomerVO vo, customerVONoon = null, customerVOAfternoon = null;
//
//		List<IVisitCustomerVO> visitCustomerNoonVOs = new ArrayList<IVisitCustomerVO>();
//
//		List<IVisitCustomerVO> visitCustomerAfternoonVOs = new ArrayList<IVisitCustomerVO>();
//
//		long conflictTime, conflictTimeAfternoon;
//
//		for (Integer integer : map.keySet()) {
//
//			mapItem = map.get(integer);
//
//			if (2 < mapItem.size()) {
//				// 大于2个
//				return true;
//			}
//
//			vo = mapItem.get(0);
//
//			time = vo.getTime();
//
//			if (time.before(noon)) {
//
//				timenoon = time;
//
//				customerVONoon = vo;
//
//			} else {
//				afternoonTime = time;
//
//				customerVOAfternoon = vo;
//			}
//
//			vo = mapItem.get(1);
//
//			time = vo.getTime();
//
//			if (time.before(noon)) {
//
//				customerVONoon = vo;
//				timenoon = time;
//			} else {
//				afternoonTime = time;
//				customerVOAfternoon = vo;
//
//			}
//
//			if (null == afternoonTime || null == timenoon || null == customerVOAfternoon || null == customerVONoon) {
//				// 没有区分上下午 可能 上下午派单多余一个
//				return true;
//			}
//			// 上午 1h，午休1h
//
//			conflictTime = timenoon.getTime() + 3600000 * 2 ;
//
//			conflictTimeAfternoon = customerVOAfternoon.getTime().getTime();
//
//			if (conflictTime > conflictTimeAfternoon) {
//				// 时间冲突
//
////				List<IVisitCustomerVO> visitCustomerNoon = lists.get(0);
//
////				List<IVisitCustomerVO> visitCustomerAfternoon = lists.get(1);
//
//				customerVONoon.setConflictTime(one);
//
//				customerVOAfternoon.setConflictTime(one);
//
//				visitCustomerAfternoonVOs.add(customerVOAfternoon);
//
//				visitCustomerNoonVOs.add(customerVONoon);
//			}
//		}
//
//		visitLists.add(visitCustomerNoonVOs);
//
//		visitLists.add(visitCustomerAfternoonVOs);
//
//		return true;
//
//	}
//
//	/**
//	 * 8(靳强住址：-上海市七宝镇) 9(李四住址：-上海市浦东新区世纪大道) (客户地址33)上海市新场地铁站 1(31077.3006米)
//	 * 0(26427.8561米) (客户地址32)上海市鹤沙航城地铁站 0(23674.2962米) 1(18819.3745米)
//	 * 
//	 * [clientId=32, staffId=8, distance=, duration=4359], [ Visit [clientId=33,
//	 * staffId=8, distance=31077.304462913366, duration=4139], Visit [clientId=32,
//	 * staffId=8, distance=26427.859369257796, duration=4179], Visit [clientId=33,
//	 * staffId=9, distance=23674.299127004662, duration=2746], Visit [clientId=32,
//	 * staffId=9, distance=18819.376868572974, duration=2258] ]
//	 * 
//	 * 8(靳强住址：-上海市七宝镇) 9(李四住址：-上海市浦东新区世纪大道) 32(上海市鹤沙航城地铁站) 1(26427.859369257796)
//	 * 0(18819.376868572974)
//	 * 
//	 * 
//	 * 33(上海市新场地铁站) 0(31077.304462913366) 1(23674.299127004662)
//	 * 
//	 * 时间
//	 * 
//	 * 32(上海市鹤沙航城地铁站) 1(4179) 0 0(2258)
//	 * 
//	 * 33(上海市新场地铁站) 0(4139) 1(2746)
//	 * 
//	 */
//	@Override
//	public List<IVisitCustomerVO> getGenreateResult(String token, Function<String, String> cacheFuction,
//			List<IVisitCustomerVO> customerVOs, String key) {
//
//		// 利用时间选最优
//		HashOperations<String, String, Object> hashOperations = redisTemplate.opsForHash();
//
//		String visistKey = cacheFuction.apply(token);
//
//		List<Object> visits = hashOperations.values(visistKey);
//
//		if (0 == visits.size()) {
//			return new ArrayList<IVisitCustomerVO>();
//		}
//
//		int len = (int) Math.sqrt(visits.size());
//		
//		LOGGER.debug("len: {}" , len);
//		
//		double[][] data = new double[len][];
//
////		Map<Integer, List<Double>> map = new HashMap<>();
//
////		List<Double> item;
//
//		int id;
//
//		Map<Integer, List<Visit>> mapVisit = new HashMap<Integer, List<Visit>>();// [len][];
//
//		int i = 0, j = 0;
//
////		Visit[] visitsItem = null;
//
//		List<Visit> visitsItem;
//
////		[
////			Visit [clientId=33, staffId=8, distance=31077.304462913366, duration=4139], 
////			Visit [clientId=32, staffId=9, distance=18819.376868572974, duration=2258]
////		]
////		[
////			Visit [clientId=33, staffId=9, distance=23674.299127004662, duration=2746], 
////			null
////		]
//		/**
//		 * visitsItem = mapVisit[i];
//		 * 
//		 * // if (null == visitsItem) { // // visitsItem = new Visit[len]; // // i = 0;
//		 * // // visitsItem[i] = visit; // // System.out.println("i: " + i + ", j: " + j
//		 * + ", visit:" + visit); // // mapVisit[j] = visitsItem; // // j++; // } else {
//		 * // // // i++; // System.out.println("i: " + i + ", j: " + j + ", visit:" +
//		 * visit); // // visitsItem[i] = visit; // }
//		 */
//
//		// TODO 过滤 时间为 null 的 也就是找不到路径规划的
//		for (Object obj : visits) {
//
//			Visit visit = (Visit) obj;
//
//			id = visit.getClientId();
////			item = map.get(id);
//
//			visitsItem = mapVisit.get(id);
//
//			if (null == visitsItem) {
//				visitsItem = new ArrayList<Visit>();
//
//				visitsItem.add(visit);
//
//				mapVisit.put(id, visitsItem);
//
//			} else {
//
//				visitsItem.add(visit);
//			}
////
////			if (null == item) {
////				item = new ArrayList<>();
////
////				item.add(visit.getDuration().doubleValue());
////
////				map.put(id, item);
////
////			} else {
////				item.add(visit.getDuration().doubleValue());
////			}
//		}
//
//		i = 0;
//		j = 0;
//
//		// 值排序 防止产生错误数据
//		for (Integer integer : mapVisit.keySet()) {
//
//			mapVisit.get(integer).sort((a, b) -> a.getStaffId() - b.getStaffId());
//		}
//
//		double[] itemData;
//
//		List<Visit> itemList;
//
//		for (Integer integer : mapVisit.keySet()) {
//
//			itemList = mapVisit.get(integer);
//
//			itemData = new double[len];
//
//			for (Visit d : itemList) {
//				itemData[i] = d.getDuration();
//				i++;
//			}
//			data[j] = itemData;
//
//			j++;
//			i = 0;
//		}
//
//		Hungary hungary = new Hungary(data);
//
//		hungary.algrm();
//
//		/**
//		 * 结果以二维数组的形式返回，其中每个子数组表示一个赋值。每个赋值的第一个元素表示列编号，第二个元素表示dataMatrix的行编号。
//		 */
//		int[][] result = hungary.getMatch();
//
//		Visit[][] visitsArray = new Visit[len][];
//		
//		
//
//		i = 0;
//
//		for (Integer ks : mapVisit.keySet()) {
//
//			visitsItem = mapVisit.get(ks);
//
//			visitsArray[i] = visitsItem.stream().toArray(Visit[]::new);
//
//			i++;
//		}
//
//		Map<Integer, Visit> results = new HashMap<Integer, Visit>();
//
//		Visit value;
//
//		int index = 0;
//		
//		byte selected = 1;
//
//		int one = 1;
//
//		for (i = 0; i < result.length; i++) {
//
//			index = BinarySearch.binarySearchByInteger(result[i], one);
//
//			if (-1 == index) {
//
//				for (int k = 0; k < result[i].length; k++) {
//
//					if (result[i][k] == one) {
//						index = k;
//					}
//				}
//			}
//			value = visitsArray[i][index];
//			
//			value.setSelected(selected);
//			
//			// 更新 visit
//			
//			hashOperations.put(visistKey, "hash-" + value.getClientId()+ "-" + value.getStaffId(), value);
//
//			results.put(value.getClientId(), value);
//		}
//		
//		// 更新visit结果
//		
//	
//
//		// 保存匈牙利算法
//
//		// 过滤指定的
////		customerVOs = customerVOs.stream().filter(e -> 0 == e.getAssignPersonnel()).collect(Collectors.toList());
//
////		VisitCustomer[] visitCustomers = new VisitCustomer[len];
////
////		VisitCustomer visitCustomer;
//
////		i = 0;
//
////		String key = RedisConstant.getAlgResultToDBKey(token);
//
//		for (IVisitCustomerVO iVisitCustomerVO : customerVOs) {
//
//			id = iVisitCustomerVO.getId();
//
//			value = results.get(iVisitCustomerVO.getId());
//
//			if (null == value) {
//				continue;
//			}
//
//			iVisitCustomerVO.setDistance(value.getDistance());
//
//			iVisitCustomerVO.setDuration(value.getDuration().intValue());
//
//			iVisitCustomerVO.setUserId(value.getStaffId());
//
//			iVisitCustomerVO.setUserName(value.getStaffName());
//
////			visitCustomer = CopyEntity.copyEntity(iVisitCustomerVO, VisitCustomer.class);
////
////			insertPropteris(visitCustomer);
//
////			visitCustomer.setId(null);
//
////			visitCustomers[i] = visitCustomer;
//
////			hashOperations.put(key, id+"", visitCustomer);
//
////			i++;
//		}
//
////		this.batchInsert(visitCustomers);
//
//		// 删除
////		cleanCacheByVisitCustomer(token);
//
//		return customerVOs;
//	}
//	/**
//	 * 清理数据
//	 * @param token
//	 */
//	private void cleanCacheByVisitCustomer(String token) {
//
//		java.util.Collection<String> collection = new ArrayList<>();
//
//		collection.add(RedisConstant.getPageNumKey(token));
//
//		collection.add(RedisConstant.getVisitCustomerKey(token));
//
//		collection.add(RedisConstant.getVisitDistanceKey(token));
//
//		collection.add(RedisConstant.getVisitKeyNoon(token));
//
//		collection.add(RedisConstant.getVisitKeyAfterNoon(token));
//
//		collection.add(RedisConstant.getVisitTimeKey(token));
//
//		collection.add(RedisConstant.getAssignKey(token));
//
//		collection.add(RedisConstant.getAlgNoonKey(token));
//
//		collection.add(RedisConstant.getAlgAfternoonKey(token));
//
//		redisTemplate.delete(collection);
//	}
//
//	@Resource
//	public void setRedisTemplate(RedisTemplate<String, Object> redisTemplate) {
//		this.redisTemplate = redisTemplate;
//	}
//
//	@Resource
//	public void setHttpRequest(HttpRequest httpRequest) {
//		this.httpRequest = httpRequest;
//	}
//
//	@Override
//	public List<List<IVisitCustomerVO>> distinguishBetweenMorningAndAfternoon(List<IVisitCustomerVO> customerVOs) {
//
//		List<List<IVisitCustomerVO>> lists = new ArrayList<List<IVisitCustomerVO>>();
//
//		List<IVisitCustomerVO> noonCustomerVOs = new ArrayList<IVisitCustomerVO>();
//
//		List<IVisitCustomerVO> afternoonCustomerVOs = new ArrayList<IVisitCustomerVO>();
//
//		Time time;
//
//		for (IVisitCustomerVO iVisitCustomerVO : customerVOs) {
//
//			time = iVisitCustomerVO.getTime();
//
//			if (time.before(noon)) { // 12 点之前
//				noonCustomerVOs.add(iVisitCustomerVO);
//				continue;
//			}
//
//			// 12 点之后
//			afternoonCustomerVOs.add(iVisitCustomerVO);
//		}
//
//		lists.add(0, noonCustomerVOs);
//
//		lists.add(1, afternoonCustomerVOs);
//
//		return lists;
//	}
//
//	@Override
//	public <VO extends IStatisticsVisitVO> PageResponseData<VO> statisticsVisit(IPage page) {
//
//		VisitCustomerMapper visitCustomerMapper = this.getBaseMapper();
//
//		page.setSelectCount(800);
//
//		List<VO> vos = visitCustomerMapper.statisticsVisit(page);
//
//		return new PageResponseData<VO>(0, vos);
//	}
//
//	@Override
//	public <VO extends IStatisticsVisitVO> PageResponseData<VO> statisticsVisitBySearch(
//			ISearchByVisitCustomerParam searchByVisitCustomerParam) {
//
//		IPage page = (IPage) searchByVisitCustomerParam;
//
//		VisitCustomerMapper visitCustomerMapper = this.getBaseMapper();
//
//		page.setSelectCount(800);
//
//		List<VO> vos = visitCustomerMapper.statisticsVisit(searchByVisitCustomerParam);
//
//		return new PageResponseData<VO>(0, vos);
//
//	}
//
////	@Override
//////	public <VO> PageResponseData<VO> getLookVisit(IVisitCustomerRecordOfDay visitCustomerRecordOfDay) {
////		
////		
////		
////		return null;
////	}
//
//	protected <S extends IPage> String sqlByGetCounttAfterProcesser(S param) {
//
////		IVisitCustomerRecordOfDay customerRecordOfDay = (IVisitCustomerRecordOfDay) param;
////		
////		Long createTime = customerRecordOfDay.getCreteTime();
////		
////		
////		Long[] longs = TimeUtil.getDayStartOfEndByTimStamp(createTime);
//
//		return this.sqlByGetCount(condition(param));
//	}
//
//	protected <S> String condition(S param) {
//
//		IVisitCustomerRecordOfDay customerRecordOfDay = (IVisitCustomerRecordOfDay) param;
//
//		Long createTime = customerRecordOfDay.getCreateTime();
//
//		long[] longs = TimeUtil.getDayStartOfEndByTimStamp(createTime * 1000);
//
//		return " admin_id = " + customerRecordOfDay.getAdminId() + " and day between " + longs[0] + " and " + longs[1];
//
//	}
//
//	protected <S extends IPage> String sqlByGetPageListAfterProcesser(S param) {
//		return this.sqlByGetPageList(" and " + condition(param));
//	}
//
//	protected List<IVisitCustomerVO> getLists(ListOperations<String, Object> listOperations, String algKey,
//			String token) {
//
//		List<List<IVisitCustomerVO>> lists = getListsFromIVisitCustomerVO(listOperations, algKey);
//
//		if (null != lists && 0 == lists.size()) {
//			return null;
//		}
//
//		List<IVisitCustomerVO> customerVOs = new ArrayList<IVisitCustomerVO>();
//
//		for (List<IVisitCustomerVO> visitCustomerVO : lists) {
//
//			customerVOs.addAll(visitCustomerVO);
//		}
//
//		return customerVOs;
//	}
//
//	@Override
//	public <VO extends IStaffInfoVO> int updateGenerateResult(List<VO> staffInfoVOs, IUpdateGenereateResult[] ids,
//			String token) {
//
//		ListOperations<String, Object> listOperations = redisTemplate.opsForList();
//
//		String algKey = RedisConstant.getAlgResultKey(token);
//
//		List<IVisitCustomerVO> customerVOs = getLists(listOperations, algKey, token);
//
//		if (null == customerVOs) {
//			return 0;
//		}
//
//		Map<Integer, IVisitCustomerVO> map = ListConvertMap.listToMap(customerVOs, IVisitCustomerVO::getId);
//
//		Map<Integer, VO> mapVOs = ListConvertMap.listToMap(staffInfoVOs, IStaffInfoVO::getId);
//
//		// id ----> 找出要调换的 userId
//
//		IStaffInfoVO staffInfoVO;
//
//		int userId;
//
//		String origin, dest;
//
//		byte status = 1;
//
//		String updateKey = RedisConstant.getUpdateKey(token);
//
//		// 先清空
//		redisTemplate.delete(updateKey);
//
//		for (int i = 0; i < ids.length; i++) {
//
//			IVisitCustomerVO customerVO = map.get(ids[i].getId());
//
//			userId = ids[i].getUserId();
//
//			customerVO.setUserId(userId);
//
//			staffInfoVO = mapVOs.get(userId);
//
//			if (null == staffInfoVO) {
//
//				System.out.println("userId: " + userId + ", pId: " + ids[i].getId());
//				System.out.println("staffInfoVO: " + staffInfoVOs.toString());
//
//				throw new RuntimeException("找不到员工信息");
//			}
//
//			customerVO.setMeLatitude(staffInfoVO.getLatitude());
//
//			customerVO.setMeLongitude(staffInfoVO.getLongitude());
//
//			customerVO.setUserName(staffInfoVO.getStaffName());
//
//			// 获取时间
//
//			origin = staffInfoVO.getLongitude() + "," + staffInfoVO.getLatitude();
//
//			dest = customerVO.getLongitude() + "," + customerVO.getLatitude();
//
//			httpRequest.getBusRoutePlanning(origin, dest, staffInfoVO.getAreaName(), customerVO.getCity(),
//					GeoRegeoPlanning.class, t -> {
//
//						GeoRegeoPlanning geoRegeoPlanning = t.getBody();
//
//						if (0 == geoRegeoPlanning.getCount()) {
//
//							customerVO.setAddressStatus(status);
//
//							return;
//						}
//
//						GeoRoute route = geoRegeoPlanning.getRoute();
//
//						List<GeoTransits> geoTransits = route.getTransits();
//						// 默认取第一个
//
//						GeoTransits geoTransit = geoTransits.get(0);
//
//						customerVO.setDuration(geoTransit.getDuration());
//
//						listOperations.leftPush(updateKey, customerVO);
//					});
//		}
//		return 1;
//	}
//
//	@Override
//	public List<List<IVisitCustomerVO>> getUpdateGenerateResult(String token) {
//
//		ListOperations<String, Object> listOperations = redisTemplate.opsForList();
//
//		String algKey = RedisConstant.getAlgResultKey(token);
//
//		List<List<IVisitCustomerVO>> lists = getListsFromIVisitCustomerVO(listOperations, algKey);
//
//		if (null != lists && 0 == lists.size()) {
//			return null;
//		}
//
////		List<IVisitCustomerVO> customerVOs = new ArrayList<IVisitCustomerVO>();
////		
////		for (List<IVisitCustomerVO> visitCustomerVO : lists) {
////			
////			customerVOs.addAll(visitCustomerVO);
////		}
////		
//		String updateKey = RedisConstant.getUpdateKey(token);
//
//		// 更新结果
//		List<Object> visitCustomerVOs = listOperations.range(updateKey, 0, listOperations.size(updateKey));
//
//		Map<Integer, Object> mapVisit = ListConvertMap.listToMap(visitCustomerVOs, e -> ((IVisitCustomerVO) e).getId());
//
////		
////		Map<Integer, IVisitCustomerVO> mapVisit = ListConvertMap.listToMap(customerVOs, IVisitCustomerVO::getId);
////		
//		IVisitCustomerVO visit;
////		
////		for (Object object : visitCustomerVOs) {
////			
////			visit = (IVisitCustomerVO) object;
////			
////			mapVisit.remove(visit.getId());
////		}
////		
////		customerVOs = new ArrayList<IVisitCustomerVO>();
////		
////		for (Integer integer : mapVisit.keySet()) {
////			
////			customerVOs.add(mapVisit.get(integer));
////		}
////		
////		for (Object object : visitCustomerVOs) {
////			
////			customerVOs.add((IVisitCustomerVO) object);
////		}
//
//		int i = -1;
//
//		int j = 0;
//
//		for (List<IVisitCustomerVO> list : lists) {
//
//			for (IVisitCustomerVO vo : list) {
//
//				visit = (IVisitCustomerVO) mapVisit.get(vo.getId());
//
//				i++;
//
//				if (null == visit) {
//					continue;
//				}
//
//				list.set(i, visit);
//			}
//
//			i = -1;
//
//			listOperations.set(algKey, j, list);
//
//			j++;
//		}
//
//		return lists;
//	}
//
//	@Override
//	public Integer[][] noonAndAfternoonAssignIds(List<IVisitCustomerVO> customerVOs) {
//
//		int size = customerVOs.size();
//		Integer[][] res = new Integer[2][];
//
//		Integer[] noonIds = new Integer[size], afernoonIds = new Integer[size];
//
//		IVisitCustomerVO customerVO;
//
//		int i = 0, j = 0, k = 0;
//
//		for (; i < size; i++) {
//
//			customerVO = customerVOs.get(i);
//
//			if (0 == customerVO.getAssignPersonnel()) {
//				// 过滤掉非指派的
//				continue;
//			}
//
//			if (customerVO.getTime().before(noon)) {
//				// 上午
//				noonIds[j] = customerVO.getUserId();
//
//				j++;
//
//				continue;
//			}
//
//			afernoonIds[k] = customerVO.getUserId();
//
//			k++;
//		}
//
//		Integer[] newNoonIds = new Integer[j];
//
//		Integer[] newAfernoonIds = new Integer[k];
//
//		System.arraycopy(noonIds, 0, newNoonIds, 0, j);
//
//		System.arraycopy(afernoonIds, 0, newAfernoonIds, 0, k);
//
//		res[0] = newNoonIds;
//
//		res[1] = newAfernoonIds;
//
//		return res;
//	}
//
//	/**
//	 *  有 131723 这个key 代表 二访
//	 *  99808 --> 首访核单状态
//	 *  130418 ---> 回访核单状态
//	 *  
//	 */
//	@Override
//	public <VO extends IVisitCustomerVO, R> List<VO> dataFromExploringHorses(
//			IExploringHorsesResponse<R> exploringHorsesResponse, Class<VO> targetClass, int adminId,
//			VisitRequestParam param) {
//
//		if (0 != exploringHorsesResponse.getCode()) {
//			return new ArrayList<VO>(0);
//		}
//
//		IData<Map<?, ?>> data = (IData<Map<?, ?>>) exploringHorsesResponse.getData();
//
//		if (0 == data.getTotalCount()) {
//			return new ArrayList<VO>(0);
//		}
//		
//		List<ConditionItem> conditionItems = param.getConditions().getConditionItems();
//		
//		Integer type = null;
//		
//		int key = 0;
//		// 处理条件
//		for (ConditionItem conditionItem : conditionItems) {
//			
//			key = conditionItem.getName();
//			
//			type = CONDITION_MAP.get(key);
//			
//			if (null == type) {
//				continue;
//			}
//			
//			break;
//		}
//		
//		if (null == type) {
//			throw new RuntimeException("搜索条件不是前道、后道、二访");
//		}
//		
//		
//		String tanmaAssignColumn = ASSIGN_COLUMN.get(key);
//		
//		String timeKey = VISIT_TIME_COLUMN.get(key);
//		
//		LOGGER.debug("tanmaAssignColumn: {}, key: {}", tanmaAssignColumn, key);
//		
//		byte typeByte = type.byteValue();
//		
//
//		List<Map<?, ?>> list = data.getData();
//
//		List<VO> vos = new ArrayList<VO>();
//
//		VO vo;
//		Map<?, ?> address;
//
//		List<Map<?, ?>> fullAddress;
//
//		String assginName;
//		String salesTime;
//		
//
//		int i = 0;
//
//		for (Map<?, ?> map : list) {
//
//			try {
//				vo = targetClass.newInstance();
//
//				vo.setCompanyName((String) map.get("corpName"));
//
//				fullAddress = (List<Map<?, ?>>) map.get("fullAddress");
//
//				if (null != fullAddress) {
//
//					address = fullAddress.get(0);
//
//					String locationAddress = address.get("locationAddress").toString();
//					String adressValue = address.get("address").toString();
//
//					if (!"".equals(locationAddress)) {
//						vo.setCompanyAddress(adressValue);
//					} else {
//						vo.setCompanyAddress(locationAddress);
//					}
//
//					vo.setLongitude((Double) address.get("longitude"));
//
//					vo.setLatitude((Double) address.get("latitude"));
//				} else {
//
//					String companyAddress = (String) map.get("93495");
//
//					vo.setCompanyAddress(companyAddress);
//				}
//
//				if (null == vo.getCompanyAddress()) {
//					// 没有地址
//					
//					LOGGER.debug("公司： {}没有地址", vo.getCompanyAddress());
//					
//					i++;
//					continue;
//				}
//				
//				
//				// 指派
//				assginName = (String) map.get(tanmaAssignColumn);
//
//				if (null != assginName && 0 != assginName.length()) {
//					vo.setUserName(assginName);
//					vo.setAssignPersonnel(1);
//				}
//				
//				vo.setCustomerId((Long) map.get("customerId"));
//
//				vo.setQwSalesld((String) map.get("qwSalesId"));
//
//				// 时间
//				salesTime = (String) map.get(timeKey);
//				
//				if (null == salesTime) {
//					// 没有指派时间
//					i++;
//					LOGGER.debug("公司： {}没有指派时间", vo.getCompanyAddress());
//					continue;
//				}
//				
//				int[] countOccurrences = StringUtil.countOccurrences(salesTime, ":");
//
//				if (2 <= countOccurrences[0]) {
//					salesTime = salesTime.substring(0, countOccurrences[1] - 1);
//				}
//				
//
//				String prov = (String) map.get("99805");
//
//				String provRep = AREA_DATA.get(prov);
//
//				if (null != provRep) {
//					vo.setAreaName(provRep);
//				} else {
//					
//					if (-1 == prov.indexOf("省")) {
//						prov = prov.concat("省");
//					}
//					
//					vo.setAreaName(prov);
//				}
//				
//				vo.setCity(map.get("99806").toString());
//
//				vo.setDay(TimeUtil.getDayStartStamp(salesTime));
//
//				vo.setTime(TimeUtil.getTime(salesTime));
//
////				departNamea = map.get("salesDeptNames").toString();
////
////				if (-1 != departNamea.indexOf("后道")) {
////					vo.setType((byte) 1);
////				} else {
////					vo.setType((byte) 0);
////				}
//
//				vo.setType(typeByte);
//				
//				vo.setId(i);
//
//				vo.setAdminId(adminId);
//
//				vos.add(vo);
//
//				i++;
//
//			} catch (Exception e) {
//				e.printStackTrace();
//			}
//		}
//		return vos;
//	}
//
//	@Override
//	public <VO extends IVisitCustomerVO, R> List<VO> dataFromExploringHorsesManyRuslt(
//			List<IExploringHorsesResponse<R>> exploringHorsesResponse, Class<VO> targetClass, int adminId,
//			VisitRequestParam[] param) {
//		
//		List<VO> vos = new ArrayList<VO>();
//		
//		int i = 0;
//		
//		for (IExploringHorsesResponse<R> iExploringHorsesResponse : exploringHorsesResponse) {
//			
//			vos.addAll(dataFromExploringHorses(iExploringHorsesResponse, targetClass, adminId, param[i]));
//			i++;
//			
//		}
//		
//		return vos;
//	}
//
//}